package com.thinking.in.spring.bean.definition;

import com.think.in.spring.ioc.overview.domain.User;
import com.thinking.in.spring.bean.factory.DefaultUserFactory;
import com.thinking.in.spring.bean.factory.UserFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Iterator;
import java.util.ServiceLoader;

/**
 *
 * bean 实例化的方式 - 特殊方式 ：
 *
 * @author : zjj
 * @date : 2021/12/28 17:09
 */
public class SpecialBeanInstantiationDemo {

    public static void main(String[] args) {
        // 应用上下文
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("META-INF/special-bean-instantiation-context.xml");

        instantiationBeanByAutowireCapableBeanFactory(applicationContext);

        instantiationBeanByServiceLoaderFactoryBean(applicationContext);
    }

    /**
     * 通过 AutowireCapableBeanFactory 的方式,实例化 Bean
     * @param applicationContext    Spring 容器
     */
    private static void instantiationBeanByAutowireCapableBeanFactory(ApplicationContext applicationContext){
        // 通过applicationContext 获取 AutowireCapableBeanFactory
        AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();
        // 这里的类型 一定要是实现类，不能是接口，否则会报错
        // 通过 AutowireCapableBeanFactory 获取到 UserFactory
        DefaultUserFactory bean = autowireCapableBeanFactory.createBean(DefaultUserFactory.class);
        System.out.println(bean.createUser());
    }

    /**
     * 通过 ServiceLoaderFactoryBean 的方式 ,来实例化Bean
     * @param applicationContext        Spring 容器
     */
    private static void instantiationBeanByServiceLoaderFactoryBean(ApplicationContext applicationContext){
        ServiceLoader<UserFactory> serviceLoader = applicationContext.getBean("userFactoryServiceLoader",ServiceLoader.class);

        displayServiceLoader(serviceLoader);
    }


    private static void displayServiceLoader(ServiceLoader<UserFactory> serviceLoader){
        Iterator<UserFactory> iterator = serviceLoader.iterator();
        while (iterator.hasNext()) {
            UserFactory next = iterator.next();
            System.out.println(next.createUser());
        }
    }

    /**
     * serviceLoader 原生demo
     */
    private static void demoServiceLoader(){
        ServiceLoader<UserFactory> load = ServiceLoader.load(UserFactory.class, Thread.currentThread().getContextClassLoader());
        displayServiceLoader(load);
    }
}
